import 'package:flutter/material.dart';
import 'package:freesic/component/player/proxy.dart';

import 'package:hive/hive.dart';
import 'package:just_audio/just_audio.dart';

import 'package:freesic/part/part.dart';

export 'package:freesic/component/player/bottom_player_bar.dart';
export 'package:freesic/component/player/lryic.dart';

part 'persistence.dart';
part 'play_queue.dart';

// key which save playing music to local preference
// const String _PREF_KEY_PLAYING = "quiet_player_playing";

// key which save playing music list to local preference
// const String _PREF_KEY_PLAYLIST = "quiet_player_playlist";

// key which save playing list token to local preference
// const String _PREF_KEY_TOKEN = "quiet_player_token";

// key which save playing mode to local preference
// const String _PREF_KEY_PLAY_MODE = "quiet_player_play_mode";

extension PlayModeGetNext on LoopMode {
  LoopMode get next {
    if (this == LoopMode.all) {
      // TODO shuffle
      // return LoopMode.shuffle;
      // } else if (this == LoopMode.shuffle) {
      return LoopMode.one;
    } else {
      return LoopMode.all;
    }
  }
}

extension FreesicPlayerExt on BuildContext {
  AudioPlayer get player {
    return ScopedModel.of<QuietModel>(this).player;
  }

  AudioPlayer get listenPlayerValue {
    return ScopedModel.of<QuietModel>(this, rebuildOnChange: true).player;
  }

  PlayerState get playbackState => listenPlayerValue.playerState;

  LoopMode get playMode => listenPlayerValue.loopMode;

  List<IndexedAudioSource>? get playingSequence => listenPlayerValue.sequence;
}

/* 
extension MusicPlayerValueExt on MusicPlayerValue {
  Music? get current => metadata == null ? null : Music.fromMetadata(metadata!);

  Music get requireCurrent => current!;

  List<Music> get playingList =>
      queue.queue.map((e) => Music.fromMetadata(e)).toList();
} */

/* extension PlaybackStateExt on PlaybackState {
  bool get hasError => state == PlayerState.Error;

  bool get isPlaying => (state == PlayerState.Playing) && !hasError;

  ///audio is buffering
  bool get isBuffering => state == PlayerState.Buffering;

  bool get initialized => state != PlayerState.None;
} */

@visibleForTesting
class QuietModel extends Model {
  QuietModel(Box<Map>? data) {
    player.playerStateStream.listen((event) {
      notifyListeners();
    });

    player.sequenceStream.listen((event) {
      // data!.savePlayQueue(player.sequence);
    });
    /* player.queueListenable.addListener(() {
      data!.savePlayQueue(player.queue);
    }); */

    player.loopModeStream.listen((event) {
      data!.savePlayMode(event);
    });
    // player.playModeListenable.addListener(() {
    // });

    // final MusicMetadata? metadata = data!.restoreMetadata();
    // final AudioSource? queue = data.restorePlayQueue();
    // player.setAudioSource(ConcatenatingAudioSource(children: []));
    // player.setPlayQueue(queue);
    player.setLoopMode(data!.restoreLoopMode());
    proxy.start();
  }

  AudioPlayer player = AudioPlayer();
  NeteaseMusicConvertingUrlProxy proxy = NeteaseMusicConvertingUrlProxy();
}

class Quiet extends StatefulWidget {
  const Quiet({required this.child, Key? key, this.box}) : super(key: key);

  final Widget child;

  final Box<Map>? box;

  @override
  State<StatefulWidget> createState() => _QuietState();
}

class _QuietState extends State<Quiet> {
  late QuietModel _quiet;

  late PlayingLyric _playingLyric;

  @override
  void initState() {
    super.initState();
    _quiet = QuietModel(widget.box);
    _playingLyric = PlayingLyric(_quiet.player);
  }

  @override
  Widget build(BuildContext context) {
    return ScopedModel(
      model: _quiet,
      child: ScopedModel(
        model: _playingLyric,
        child: widget.child,
      ),
    );
  }
}

extension PlayModeDescription on LoopMode {
  IconData get icon {
    if (this == LoopMode.one) {
      return Icons.repeat_one_rounded;
      // } else if (this == PlayMode.shuffle) {
      // return Icons.shuffle_rounded;
    } else {
      return Icons.repeat_rounded;
    }
  }

  String get name {
    if (this == LoopMode.one) {
      return "单曲循环";
      // } else if (this == PlayMode.shuffle) {
      // return "随机播放";
    } else {
      return "列表循环";
    }
  }
}
